package com.yunpeng.aidevice.biz.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.yunpeng.aidevice.biz.service.INoticeBizService;
import com.yunpeng.aidevice.common.constant.ConstantValues;
import com.yunpeng.aidevice.common.dto.save.DeviceNoticeParameterSaveDTO;
import com.yunpeng.aidevice.common.dto.save.NoticeUserSaveDTO;
import com.yunpeng.aidevice.common.enums.DeviceUploadDataStateEnum;
import com.yunpeng.aidevice.common.enums.ResultCodeEnum;
import com.yunpeng.aidevice.common.vo.SimpleEntityVO;
import com.yunpeng.aidevice.common.vo.device.DeviceNoticeUserConfigVO;
import com.yunpeng.aidevice.dao.constant.DictionariesConstant;
import com.yunpeng.aidevice.dao.model.entity.DeviceDO;
import com.yunpeng.aidevice.dao.model.entity.UserDO;
import com.yunpeng.aidevice.dao.model.record.NoticeConfigDO;
import com.yunpeng.aidevice.dao.model.record.RecordDO;
import com.yunpeng.aidevice.dao.service.INoticeRuleService;
import com.yunpeng.aidevice.dao.service.IUserService;
import com.yunpeng.aidevice.push.IPushService;
import com.yunpeng.common.dto.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * NoticeBizServiceImpl
 *
 * @author : Moore(hemw)
 * @date : 2020-04-28
 */
@Service
public class NoticeBizServiceImpl implements INoticeBizService {

    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(NoticeBizServiceImpl.class);
    @Resource
    private INoticeRuleService noticeRuleService;

    @Resource
    private IUserService userService;


    @Resource
    private IPushService emailPushService;

    @Override
    /**
     * 规则集合下拉菜单
     *
     * @return
     */
    public Result<JSONArray> ruleDropdownList() {
        return Result.success(noticeRuleService.ruleDropdownList());
    }

    @Override
    /**
     * 设备规则配置参数 下拉菜单
     *
     * @param scriptCodes 规则代码集合
     * @param deviceCode  设备代码
     * @return
     */
    public Result<JSONArray> ruleParameterDropdownList(List<String> scriptCodes, String deviceCode) {
        return Result.success(noticeRuleService.ruleParameterDropdownList(scriptCodes, deviceCode));
    }

    @Override
    /**
     * 删除设备的提醒用户设置
     *
     * @param scriptCode 脚本代码
     * @param userCode   用户代码
     * @param deviceCode 设备代码
     * @return
     */
    public Result<Void> removeNoticeToUser(String scriptCode, String userCode, String deviceCode) {
        if (noticeRuleService.deletedDeviceNoticeUser(deviceCode, userCode, scriptCode)) {
            return Result.success();
        }
        return Result.fail(ResultCodeEnum.REMOVE_FAILED);
    }

    @Override
    /**
     * 设备提醒用户列表
     *
     * @param deviceCode 设备代码
     * @return
     */
    public Result<List<DeviceNoticeUserConfigVO>> deviceNoticeUserList(String deviceCode) {
        List<NoticeConfigDO> noticeConfigDOList = noticeRuleService.deviceNoticeUserList(deviceCode);
        if (noticeConfigDOList == null) {
            return Result.success();
        }
        List<DeviceNoticeUserConfigVO> resultList = new ArrayList<>();
        for (NoticeConfigDO noticeConfigDO : noticeConfigDOList) {
            DeviceNoticeUserConfigVO deviceNoticeUserConfigVO = new DeviceNoticeUserConfigVO();
            deviceNoticeUserConfigVO.setId(noticeConfigDO.getId());
            deviceNoticeUserConfigVO.setOrgName(noticeConfigDO.getOrgName());
            deviceNoticeUserConfigVO.setUserCode(noticeConfigDO.getUserCode());
            deviceNoticeUserConfigVO.setUserName(noticeConfigDO.getUserName());
            deviceNoticeUserConfigVO.setScriptName(noticeConfigDO.getRuleName());
            deviceNoticeUserConfigVO.setScriptCode(noticeConfigDO.getRuleCode());
            deviceNoticeUserConfigVO.setUserPhone(noticeConfigDO.getPhone());
            deviceNoticeUserConfigVO.setUserEmail(noticeConfigDO.getEmail());
            deviceNoticeUserConfigVO.setEmailNotice(noticeConfigDO.getEmailNotice());
            deviceNoticeUserConfigVO.setPhoneMsgNotice(noticeConfigDO.getPhoneMsgNotice());
            resultList.add(deviceNoticeUserConfigVO);
        }
        return Result.success(resultList);
    }

    @Override
    /**
     * 新增提醒用户
     *
     * @param noticeUserSaveDTO 提醒用户信息
     * @param operatorCode      操作人代码
     * @return
     */
    public Result<Void> addNoticeToUser(NoticeUserSaveDTO noticeUserSaveDTO, String operatorCode) {
        if (noticeRuleService.addNoticeToUser(noticeUserSaveDTO, operatorCode)) {
            return Result.success();
        }
        return Result.fail(ResultCodeEnum.SAVE_DATA_FAILED);
    }

    @Override
    /**
     * 配置设备报警参数
     *
     * @param deviceNoticeParameterSaveDTO
     * @param operatorCode
     * @return
     */
    public Result<Void> configDeviceNoticeParameters(DeviceNoticeParameterSaveDTO deviceNoticeParameterSaveDTO, String operatorCode) {
        if (noticeRuleService.configDeviceNoticeParameters(deviceNoticeParameterSaveDTO, operatorCode)) {
            return Result.success();
        }
        return Result.fail(ResultCodeEnum.SAVE_DATA_FAILED);
    }


    //region 私有方法


    @Override
    /**
     * 1.邮件名称：
     * 温度异常提醒-设备名称－设备地址
     * <p>
     * 邮件内容：
     * 部门名称：[部门名称]
     * 异常人员：[人员名称]
     * 设备名称：[设备名称]
     * 设备地址：[设备地址]
     * 检测时间：[检测时间]
     *
     * @param deviceDO
     * @return
     */
    public Boolean noticeToUsers(DeviceDO deviceDO, RecordDO recordDO) {
        List<NoticeConfigDO> noticeConfigDOList = noticeRuleService.deviceNoticeUserList(deviceDO.getCode());
        UserDO userDO = null;
        //exception状态会有用户信息
        boolean hasUserInfo = DeviceUploadDataStateEnum.exception.getValue().equalsIgnoreCase(recordDO.getState());
        if (hasUserInfo) {
            userDO = userService.getByCode(recordDO.getUserCode());
        }
        if (noticeConfigDOList == null) {
            return false;
        }
        List<SimpleEntityVO> unKnownUserNoticeEmails = new ArrayList<>();
        List<SimpleEntityVO> exceptionNoticeEmails = new ArrayList<>();
        for (NoticeConfigDO noticeConfigDO : noticeConfigDOList) {
            if (noticeConfigDO.getEmailNotice() != null && noticeConfigDO.getEmailNotice()) {
                SimpleEntityVO simpleEntityVO = new SimpleEntityVO(noticeConfigDO.getEmail(), noticeConfigDO.getUserCode(), noticeConfigDO.getUserName());
                //温度异常规则报警，既识别出了用户，后续需要修改为可扩展的形式
                if (DictionariesConstant.INSTANCE.getSystemDeviceNoticeRuleName().equalsIgnoreCase(noticeConfigDO.getRuleCode())) {
                    exceptionNoticeEmails.add(simpleEntityVO);
                } else {
                    unKnownUserNoticeEmails.add(simpleEntityVO);
                }
            }
        }
        if (hasUserInfo && exceptionNoticeEmails.size() > 0) {
            return sendExceptionMail(deviceDO, userDO, recordDO, exceptionNoticeEmails);
        }
        if (!hasUserInfo && unKnownUserNoticeEmails.size() > 0) {
            return sendUnknownUserMail(deviceDO, recordDO, unKnownUserNoticeEmails);
        }
        LOGGER.info("execute send email,get user {} config empty user .", hasUserInfo);
        return false;
    }

    /**
     * 温度异常提醒
     *
     * @param deviceDO
     * @param userDO
     * @param recordDO
     * @param emails
     * @return
     */
    private boolean sendExceptionMail(DeviceDO deviceDO, UserDO userDO, RecordDO recordDO, List<SimpleEntityVO> emails) {
        //温度异常提醒
        String emailName = String.format("体温異常のお知らせ-%s－%s", deviceDO.getName(), deviceDO.getInstallLocation());
        StringBuilder contentBuilder = new StringBuilder();
        //异常人员
        //部门名称
        contentBuilder.append("<span>部署名：[").append(userDO.getOrganizationName()).append("]</span><br />");
        contentBuilder.append("<span>体温異常のあるスタッフ：[").append(userDO.getName()).append("]</span><br />");
        //设备名称
        contentBuilder.append("<span>設備名：[").append(deviceDO.getName()).append("]</span><br />");
        //设备地址
        contentBuilder.append("<span>設備アドレス：[").append(deviceDO.getInstallLocation()).append("]</span><br />");
        //检测温度
        contentBuilder.append("<span>測定の温度：[").append(recordDO.getRecordResult()).append("]</span><br />");
        //检测时间
        contentBuilder.append("<span>測定の時間：[").append(ConstantValues.DATE_FORMAT_L.format(recordDO.getProduceTime())).append("]</span><br />");

        try {
            emailPushService.pushMimeMessage(DictionariesConstant.INSTANCE.getMerchantNoticeMailConfig(deviceDO.getMerchantCode(), deviceDO.getTenantCode())
                    , emails, emailName, contentBuilder.toString());
        } catch (Exception e) {
            LOGGER.error("execute send exception email error,", e);
            return false;
        }
        return true;
    }


    /**
     * 未知人员异常提醒
     *
     * @param deviceDO
     * @param recordDO
     * @param emails
     * @return
     */
    private boolean sendUnknownUserMail(DeviceDO deviceDO, RecordDO recordDO, List<SimpleEntityVO> emails) {
        //未知人员异常提醒
        String emailName = emailName = String.format("未登録者のお知らせ-%s－%s", deviceDO.getName(), deviceDO.getInstallLocation());
        StringBuilder contentBuilder = new StringBuilder();
        //异常人员
        contentBuilder.append("<span style=\"display: flex; align-items: center; \">未登録者：[<img style=\"max-width: 100px; max-height: 300px;\" src=\"").append(recordDO.getRecordImages()).append("\"/>]</span><br />");
        //设备名称
        contentBuilder.append("<span>設備名：[").append(deviceDO.getName()).append("]</span><br />");
        //设备地址
        contentBuilder.append("<span>設備アドレス：[").append(deviceDO.getInstallLocation()).append("]</span><br />");
        //检测温度
        contentBuilder.append("<span>測定の温度：[").append(recordDO.getRecordResult()).append("]</span><br />");
        //检测时间
        contentBuilder.append("<span>測定の時間：[").append(ConstantValues.DATE_FORMAT_L.format(recordDO.getProduceTime())).append("]</span><br />");

        try {
            emailPushService.pushMimeMessage(DictionariesConstant.INSTANCE.getMerchantNoticeMailConfig(deviceDO.getMerchantCode(), deviceDO.getTenantCode())
                    , emails, emailName, contentBuilder.toString());
        } catch (Exception e) {
            LOGGER.error("execute send exception email error,", e);
            return false;
        }
        return true;
    }
    //endregion
}
